fn main() {
    first();
    second();
    three();
    option_some();
    match_one();
}

fn first() {
    #[derive(Debug)]
    enum IpAddrKind {
        V4,
        V6,
    }

    struct IpAddr {
        kind: IpAddrKind,
        address: String,
    }
    let home = IpAddr {
        kind: IpAddrKind::V4,
        address: String::from("127.0.0.1"),
    };

    let four = IpAddrKind::V4;
    let six = IpAddrKind::V6;

    println!("direct {:?}, struct.kind {:?}, struck.address {:?} "
             , four, home.kind, home.address);
    println!("direct {:?}", six);
}

fn second() {
    //#[derive(Debug)]
    enum IpAddr {
        V4(String),
        V6(String),
    }

    //let home = IpAddr::V4(String::from("127.0.0.1"));
    //let home_v6 = IpAddr::V6(String::from("::1"));

    enum IpAddr1 {
        V4(u8, u8, u8, u8),
        V6(String),
    }

    let home1 = IpAddr1::V4(127, 0, 0, 1);
    let home1_v6 = IpAddr1::V6(String::from("::1"));

    /*if let IpAddr::V4(text) = home {
        println!("direct {}", text);
    }

    if let IpAddr::V6(text) = home_v6 {
        println!("direct {}", text);
    }*/

    if let IpAddr1::V4(text1, text2, text3, text4) = home1 {
        println!("V4({}.{}.{}.{}) ", text1, text2, text3, text4);
    }

    if let IpAddr1::V6(text) = home1_v6 {
        println!("V6({}) ", text);
    }

    fn ip_ver(ip: IpAddr) -> () {
      match ip {
        IpAddr::V4(text) => println!("match V4({})", text),
        
        IpAddr::V6(text) => println!("match V6{}", text),
        }
    }
    ip_ver(IpAddr::V4(String::from("128.0.0.2")));
    ip_ver(IpAddr::V6(String::from("::2")));
}

fn three() {
    //#[derive(Debug)]
    enum Message {
        Write(String),
    }

    let m = Message::Write(String::from("Hello"));

    match m {
        Message::Write(text) => println!("{text}"),
    }
}

fn option_some(){
    let x = Some(4);
    let y = Some(6);
    let z = 6;
    let sum = |x, y| {x + y};
    println!("option_some = {:?}!", x.and_then(|x| y.map(|y| sum(x, y))));

    fn sum_one(&u: &i32, &i: &Option<i32>) -> Option<i32> {
        match i {
           Some(i) => Some(i+u),
           _ => None,
        }
    }
    let sumone = sum_one(&z, &x);
    let none = sum_one(&z, &None);
    println!("x = {:?}, sumone = {:?}, none = {:?} ", x, sumone, none);

}

fn match_one(){
    let x = Some(0u8);

    match x {
        Some(2) => println!("match one in match {}", 2),
        Some(4) => println!("match one in match {}", 4),
        Some(0) => println!("match one in match {}", 0),
        _ => println!("match one in match None"),
    }

    println!("match one {:?} ", x);
}
